`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/05/20 13:51:04
// Design Name: 
// Module Name: FSM_Send_8b10b
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module FSM_Send_8b10b(
	input   		M_AXIS_Clk,
    input   		M_AXIS_nRst,
    input   		M_AXIS_tvalid,
    input   [31:0]	M_AXIS_tdata,
    input   [3:0]	M_AXIS_tkeep,
    input   		M_AXIS_tlast, 
    output   		M_AXIS_tready, 
	output	 		clk_1M,
    output 	     	Serial_out
    );

reg 		M_AXIS_tready;
reg         clk_1M;
reg         Serial_out;

parameter	FRAME_FILE_OVER = 10'b10_1111_1101; // bit流结束发送字符  K29.7
parameter	FRAME_FREE = 10'b10_1111_1100; //无数据时发送特殊字符   K28.7
parameter	FRAME_FREE_1 = 10'b11_0110_1000;

reg	[999:0] data_2_send;
reg	[39:0] 	code_2_10B;
reg	[23:0] 	Frame_Head;
reg 		Flag_Last;


reg 		Flag_OneTime_Data;
reg	[4:0] 	clk100M_cnt;	//100M时钟计数
reg	[6:0] 	clk100M_cnt_1M;	//100M计1M时钟计数值
reg	[10:0] 	clk1M_cnt;		//1M时钟计数值
wire [39:0]  Send_temp;


always @(posedge M_AXIS_Clk or negedge M_AXIS_nRst) 
begin
	if (~M_AXIS_nRst) 
		begin
			// reset function
			code_2_10B 		<= 40'd0;
			clk100M_cnt  	<= 5'd0;
			clk100M_cnt_1M	<= 7'd0;
			clk1M_cnt 		<= 11'd0;
			M_AXIS_tready 	<= 0;
			Flag_OneTime_Data  <= 1;
			Serial_out		<= 0;
			clk_1M 			<= 0;
			Flag_Last 		<= 0;
			Frame_Head 		<= 24'b11100010010_1111100110101;	//Frame_Head  巴克码组  13+11
			data_2_send <= {FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,
							FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1,FRAME_FREE_1
							};
		end
	else 
		begin	
			clk100M_cnt_1M	<= clk100M_cnt_1M + 7'd1;

			if ( (clk100M_cnt_1M ==0) | (clk100M_cnt_1M ==49) )
				clk_1M 	<= ~clk_1M; 


			if (clk100M_cnt_1M == 7'd99) 	//节拍
				begin
					clk100M_cnt_1M <= 0;  
					if(clk1M_cnt < 11'd1023)
						clk1M_cnt <= clk1M_cnt + 1;
					else 
						begin
							clk1M_cnt <= 0;
							Flag_OneTime_Data <= 1;
						end
				end

			if( clk1M_cnt < 10'd24)  //串行发送数据
					Serial_out <= Frame_Head[clk1M_cnt];
			else if(clk1M_cnt >= 10'd24 )
					Serial_out <= data_2_send[clk1M_cnt-10'd24];
			
				
			if( (Flag_OneTime_Data) & (clk100M_cnt < 5'd28 ) & (clk1M_cnt < 10'd23) )
				begin
					clk100M_cnt <= clk100M_cnt + 5'd1 ;
					if( (clk100M_cnt < 5'd26) )  //数据刷新
						begin
							case ( {M_AXIS_tlast,M_AXIS_tvalid} )  
								2'b00:	//无数据状态，发送Free
									code_2_10B[39:0] <= { FRAME_FREE,FRAME_FREE,FRAME_FREE,FRAME_FREE };
								2'b01:   //有数据状态，T_Ready拉高，接收FIFO数据
									begin
										Flag_Last <= 0;
										if( (clk100M_cnt < 5'd25) )
											M_AXIS_tready <= 1;
										else 
											M_AXIS_tready <= 0;

										if ( M_AXIS_tkeep[0] )
											code_2_10B[ 9: 0] <= { 2'b00,M_AXIS_tdata[7:0] } ;
										else
											code_2_10B[ 9: 0] <= { FRAME_FREE } ;

										if ( M_AXIS_tkeep[1] )
											code_2_10B[19:10] <= { 2'b00,M_AXIS_tdata[15:8] } ;
										else
											code_2_10B[19:10] <= { FRAME_FREE } ;

										if ( M_AXIS_tkeep[2] )
											code_2_10B[29:20] <= { 2'b00,M_AXIS_tdata[23:16] } ;
										else
											code_2_10B[29:20] <= { FRAME_FREE } ;

										if ( M_AXIS_tkeep[3] )
											code_2_10B[39:30] <= { 2'b00,M_AXIS_tdata[31:24] } ;
										else
											code_2_10B[39:30] <= { FRAME_FREE } ;

									end
								2'b10:  //down为1时，FIFO比特流传输完成标志，
									begin
										M_AXIS_tready <= 0;
										code_2_10B[39:0] <= { FRAME_FILE_OVER,FRAME_FREE,FRAME_FREE,FRAME_FREE};
									end
								2'b11:  //down为1时，FIFO比特流传输完成标志，
									begin
										if (Flag_Last == 0) 
											begin
												M_AXIS_tready <= 1;
												Flag_Last <= Flag_Last + 1;
												if ( M_AXIS_tkeep[0] )
													code_2_10B[ 9: 0] <= { 2'b00,M_AXIS_tdata[7:0] } ;
												else
													code_2_10B[ 9: 0] <= { FRAME_FREE } ;

												if ( M_AXIS_tkeep[1] )
													code_2_10B[19:10] <= { 2'b00,M_AXIS_tdata[15:8] } ;
												else
													code_2_10B[19:10] <= { FRAME_FREE } ;

												if ( M_AXIS_tkeep[2] )
													code_2_10B[29:20] <= { 2'b00,M_AXIS_tdata[23:16] } ;
												else
													code_2_10B[29:20] <= { FRAME_FREE } ;

												if ( M_AXIS_tkeep[3] )
													code_2_10B[39:30] <= { 2'b00,M_AXIS_tdata[31:24] } ;
												else
													code_2_10B[39:30] <= { FRAME_FREE } ;
											end
										else 
											begin
												M_AXIS_tready <= 0;
												code_2_10B[39:0] <= { FRAME_FILE_OVER,FRAME_FREE,FRAME_FREE,FRAME_FREE};
											end
									end
							endcase
						end
					else if(clk100M_cnt == 5'd27)
							Flag_OneTime_Data <= 0;
				end
			else 
				begin
					clk100M_cnt <= 5'd0;
				end

				



			if (clk100M_cnt > 5'd2 && clk100M_cnt < 5'd28 ) //组帧
				begin
					case ( clk100M_cnt )
						5'd 3:  data_2_send[ 39:  0] <= Send_temp[39:0];
						5'd 4:  data_2_send[ 79: 40] <= Send_temp[39:0];
						5'd 5:  data_2_send[119: 80] <= Send_temp[39:0];
						5'd 6:  data_2_send[159:120] <= Send_temp[39:0];
						5'd 7:  data_2_send[199:160] <= Send_temp[39:0];
						5'd 8:  data_2_send[239:200] <= Send_temp[39:0];
						5'd 9:  data_2_send[279:240] <= Send_temp[39:0];
						5'd10:  data_2_send[319:280] <= Send_temp[39:0];
						5'd11:  data_2_send[359:320] <= Send_temp[39:0];
						5'd12:  data_2_send[399:360] <= Send_temp[39:0];
						5'd13:  data_2_send[439:400] <= Send_temp[39:0];
						5'd14:  data_2_send[479:440] <= Send_temp[39:0];
						5'd15:  data_2_send[519:480] <= Send_temp[39:0];
						5'd16:  data_2_send[559:520] <= Send_temp[39:0];
						5'd17:  data_2_send[599:560] <= Send_temp[39:0];
						5'd18:  data_2_send[639:600] <= Send_temp[39:0];
						5'd19:  data_2_send[679:640] <= Send_temp[39:0];
						5'd20:  data_2_send[719:680] <= Send_temp[39:0];
						5'd21:  data_2_send[759:720] <= Send_temp[39:0];
						5'd22:  data_2_send[799:760] <= Send_temp[39:0];
						5'd23:  data_2_send[839:800] <= Send_temp[39:0];
						5'd24:  data_2_send[879:840] <= Send_temp[39:0];
						5'd25:  data_2_send[919:880] <= Send_temp[39:0];
						5'd26:  data_2_send[959:920] <= Send_temp[39:0];
						5'd27:  data_2_send[999:960] <= Send_temp[39:0];
					endcase
				end
		end


end

encode_8b10b U1(
	.dtin(code_2_10B[9:0]),
    .clk(M_AXIS_Clk),
    .rst_n(M_AXIS_nRst),
    .dtout(Send_temp[9:0])
	);

encode_8b10b U2(
	.dtin(code_2_10B[19:10]),
    .clk(M_AXIS_Clk),
    .rst_n(M_AXIS_nRst),
    .dtout(Send_temp[19:10])
	);

encode_8b10b U3(
	.dtin(code_2_10B[29:20]),
    .clk(M_AXIS_Clk),
    .rst_n(M_AXIS_nRst),
    .dtout(Send_temp[29:20])
	);

encode_8b10b U4(
	.dtin(code_2_10B[39:30]),
    .clk(M_AXIS_Clk),
    .rst_n(M_AXIS_nRst),
    .dtout(Send_temp[39:30])
	);

endmodule
